package com.xian.im.modules.avchat.manager;

import com.alibaba.cloud.commons.lang.StringUtils;
import com.alibaba.fastjson.JSON;
import com.xian.feign.GroupChannelClient;
import com.xian.feign.UserChannelClient;
import com.xian.im.common.constant.CommandCodeConstant;
import com.xian.im.common.constant.CommandConstant;
import com.xian.im.common.enums.UniqueTypeGenerateEnums;
import com.xian.im.common.model.dto.GroupUserDto;
import com.xian.im.common.model.session.SessionUser;
import com.xian.im.common.model.vo.UserDetail;
import com.xian.im.common.proto.MsgResponse;
import com.xian.im.common.sequence.UniqueSnowFlakeGenerate;
import com.xian.im.common.utils.sys.SpringContextHolder;
import com.xian.im.modules.im.core.IGroupUserCoreService;
import com.xian.im.modules.message.GroupHandler;
import com.xian.im.modules.message.UserHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.security.MD5Encoder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * @program: xian-im-server
 * @description: 成员管理
 * @author: liru.xian
 * @create: 2021-01-28 20:43
 */
@Slf4j
@Component
public class ImUserManager extends AbsManager {
  public static final String USER_RECORD = "user:record:";

  private final IGroupUserCoreService groupUserCoreService;
  private final UniqueSnowFlakeGenerate uniqueSnowFlakeGenerate;
  private final RedisTemplate redisTemplate;
  @Autowired
  private UserChannelClient userChannelClient;

  public ImUserManager(
      IGroupUserCoreService groupUserCoreService,
      UniqueSnowFlakeGenerate uniqueSnowFlakeGenerate,
      RedisTemplate redisTemplate) {
    this.groupUserCoreService = groupUserCoreService;
    this.uniqueSnowFlakeGenerate = uniqueSnowFlakeGenerate;
    this.redisTemplate = redisTemplate;
  }

  /**
   * 在线用户踢出
   *
   * @param userId
   * @param groupUniqueId
   * @return
   */
  public Boolean kickOut(String userId, String groupUniqueId) {
    GroupChannelClient groupChannelClient = SpringContextHolder.getBean(GroupChannelClient.class);

    Set<String> ctxIds = userChannelClient.ctxIds(userId);
    for (String ctxId : ctxIds) {
      groupChannelClient.kick(ctxId,groupUniqueId);
    }
    return Boolean.TRUE;
  }

  public Boolean mute(String userId, String groupUniqueId) {

    GroupUserDto groupUserDto = new GroupUserDto();
    groupUserDto.setGroupUniqueId(groupUniqueId);
    groupUserDto.setUserAccount(userId);
    groupUserCoreService.shutUpUser(600L, groupUserDto);
    MsgResponse response = MsgResponse.buildSuccess();
    response.setCmd(CommandConstant.GROUP_CMD);
    response.setCmdCode(CommandCodeConstant.GROUP_MEMBER_MUTE);
    String uniqueId =
        StringUtils.isBlank(response.getUniqueId())
            ? uniqueSnowFlakeGenerate.getSerialId(UniqueTypeGenerateEnums.xim_MSG.getCode())
            : response.getUniqueId();
    response.setUniqueId(uniqueId);
    response.setTimestamp(System.currentTimeMillis() + "");
    SessionUser sessionUser = userChannelClient.sessionUser(userId);
    UserDetail user = new UserDetail(sessionUser);
    response.setBody(user.getNickname() + " 被系统禁言");
    GroupHandler.groupSendAll(response, groupUniqueId);
    return Boolean.TRUE;
  }

  /**
   * 解除禁言
   *
   * @param userId
   * @param groupUniqueId
   * @return
   */
  public Boolean openMute(String userId, String groupUniqueId) {
    GroupUserDto groupUserDto = new GroupUserDto();
    groupUserDto.setGroupUniqueId(groupUniqueId);
    groupUserDto.setUserAccount(userId);
    groupUserCoreService.unmute(groupUserDto);
    MsgResponse response = MsgResponse.buildSuccess();
    response.setCmd(CommandConstant.GROUP_CMD);
    response.setCmdCode(CommandCodeConstant.GROUP_OPEN_MEMBER_MUTE);
    String uniqueId =
        StringUtils.isBlank(response.getUniqueId())
            ? uniqueSnowFlakeGenerate.getSerialId(UniqueTypeGenerateEnums.xim_MSG.getCode())
            : response.getUniqueId();
    response.setUniqueId(uniqueId);
    response.setTimestamp(System.currentTimeMillis() + "");
    SessionUser sessionUser = userChannelClient.sessionUser(userId);

    UserDetail user = new UserDetail(sessionUser);
    response.setBody("系统解除" + user.getNickname() + "禁言");
    GroupHandler.groupSendAll(response, groupUniqueId);
    return Boolean.TRUE;
  }

  /**
   * 点对点 系统消息
   *
   * @param body
   * @param userId
   */
  public void sendSystemMessage(String body, String userId) {
    UserHandler.sendSystemMessage(body, userId);
  }

  /**
   * 点对点 系统消息
   *
   * @param response
   * @param channelId
   */
  public void sendSystemMessage(MsgResponse response, String channelId) {
    UserHandler.sendSystemMessage(response, channelId);
  }

  /**
   * 记录在线
   *
   * @param account
   * @param ctxId
   */
  public void recordOnLine(String account, String ctxId) {
    ctxId = MD5Encoder.encode(ctxId.getBytes());
    redisTemplate
        .opsForValue()
        .set(USER_RECORD + ctxId + ":" + account, System.currentTimeMillis(), 20, TimeUnit.SECONDS);
  }

  /**
   * 下线记录 某一端踢下线
   *
   * @param account
   * @param ctxId
   */
  public void recordOffline(String account, String ctxId) {
    ctxId = MD5Encoder.encode(ctxId.getBytes());
    redisTemplate.delete(USER_RECORD + ctxId + ":" + account);
  }

  /**
   * 下线记录 某一端踢下线
   *
   * @param ctxId
   */
  public void recordOffline(String ctxId) {
    unBindSession(ctxId);
    ctxId = MD5Encoder.encode(ctxId.getBytes());
    Set<String> keys = keys(USER_RECORD + ctxId + "*");
    if (!keys.isEmpty()) {
      redisTemplate.delete(keys);
    }
  }

  /**
   * 是否在线
   *
   * @param account
   * @param ctxId
   */
  public Boolean isOnline(String account, String ctxId) {
    ctxId = MD5Encoder.encode(ctxId.getBytes());
    Object o = redisTemplate.opsForValue().get(USER_RECORD + ctxId + ":" + account);
    return o != null;
  }

  /**
   * 是否在线
   *
   * @param account
   */
  public Boolean isOnline(String account) {
    Set<String> keys = keys(USER_RECORD + "*" + account);
    if (!keys.isEmpty()) {
      for (String key : keys) {
        Object o = redisTemplate.opsForValue().get(key);
        if (null != o) {
          return Boolean.TRUE;
        }
      }
    }
    return Boolean.FALSE;
  }

  public static final String BIND_SESSION_CHANNEL = "bind:session:channel:";

  public Boolean bindSession(SessionUser user, String channelId) {
    redisTemplate.opsForValue().set(BIND_SESSION_CHANNEL + channelId, user, 30, TimeUnit.SECONDS);
    return Boolean.TRUE;
  }

  public Boolean hasLogin(String ctxId) {
    return redisTemplate.hasKey(BIND_SESSION_CHANNEL + ctxId);
  }

  public Boolean unBindSession(String ctxId) {
    return redisTemplate.delete(BIND_SESSION_CHANNEL + ctxId);
  }

  public SessionUser getSession(String ctxId) {
    Object o = redisTemplate.opsForValue().get(BIND_SESSION_CHANNEL + ctxId);
    if (o != null) {
      return JSON.parseObject(o.toString(), SessionUser.class);
    }
    return null;
  }
}
